﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

using ProjectBase.Core;
using ProjectBase.Core.Web;
using ProjectBase.Mvc;
using ProjectBase.Mvc.Controllers;

using Survey.Common;
using Survey.Common.Business;
using Survey.Common.Business.Services;
using Survey.Common.Controllers.Services;
using Survey.Common.Models.Services;
using Survey.Entity.Services;

namespace Survey.Mvc.Controllers.Services
{
    /// <summary>
    ///     All actions for Article
    /// </summary>
    public class ArticleController
        : EntityController<Article, ArticleFilter, IArticleModel, IArticleFacade>, IArticleController
    {
        #region OnList
        /// <summary>
        ///     Provides columns for List view
        /// </summary>
        protected override IEnumerable<IItemToDisplay> LoadItemsToDisplay(ArticleFilter filter)
        {
            filter.AddPropertyToProjectionList(() => Model.Item.ID);
            filter.AddPropertyToProjectionList(() => Model.Item.Code);
            filter.AddPropertyToProjectionList(() => Model.Item.Title);
            filter.AddPropertyToProjectionList(() => Model.Item.ReleaseDate);
            filter.AddPropertyToProjectionList(() => Model.Item.LastUpdateDate);
            filter.AddPropertyToProjectionList(() => Model.Item.IsVisible);
            filter.AddPropertyToProjectionList(() => Model.Item.ArticleCategory.Code,
                () => Model.Item.ArticleCategoryCode);
            filter.AddPropertyToProjectionList(() => Model.Item.ArticleGroup.Code,
                () => Model.Item.ArticleGroupCode);

            return Facade.Find(filter)
                .Select(i => new ItemToDisplay
                {
                    ID = i.IDToDisplay,
                    Description = i.ToDisplay(),
                    Items = new List<ICellDescription>
                    {
                        i.Cell(() => i.Title),
                        i.Cell(() => i.ArticleCategoryCode, () => i.ArticleCategory.Code),
                        i.Cell(() => i.ArticleGroupCode, () => i.ArticleGroup.Code),
                        i.Cell(() => i.LastUpdateDate),
                        i.Cell(() => i.IsVisible),
                        i.Cell(() => i.Code, new CellDescription {MaxCellLength = 50}),
                        i.Cell(() => i.ID, new CellDescription {Align = Align.right, Format = "N0"}),
                    }
                } as IItemToDisplay);
        }

        /// <summary>
        ///     Provides columns for Excel
        /// </summary>
        protected override IEnumerable<IEnumerable<IExCell>> LoadExcelItemsToDisplay(ArticleFilter filter)
        {
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.ID);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.Code);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.Title);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.ReleaseDate);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.LastUpdateDate);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.IsVisible);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.ArticleCategory);
            Model.Filter.AddPropertyToProjectionList(() => Model.Item.ArticleGroup);

            return Facade.Find(filter)
                .Select(i => new List<IExCell>
                {
                    i.ExCell(() => i.ID),
                    i.ExCell(() => i.Code),
                    i.ExCell(() => i.Title),
                    i.ExCell(() => i.ReleaseDate),
                    i.ExCell(() => i.IsVisible),
                    i.ExCell(() => i.ArticleCategory),
                    i.ExCell(() => i.ArticleCategoryCode),
                    i.ExCell(() => i.ArticleGroup),
                    i.ExCell(() => i.ArticleGroupCode),
                    i.ExCell(() => i.Description),
                });
        }
        #endregion OnList

        #region OnBind
        #endregion OnBind

        #region OnBefore
        protected override void OnBeforeDetail(int id)
        {
            base.OnBeforeDetail(id);
            this.AddAction(Str.Business.Services.Upload, Url);
            this.AddButton(Str.Business.Services.Upload, Url);
            FillModel();
        }

        protected override void OnBeforeEdit(int id)
        {
            base.OnBeforeEdit(id);
            FillModel();
            AddRefreshButton();
        }

        protected override void OnBeforeNew()
        {
            base.OnBeforeNew();
            AddRefreshButton();
        }

        protected virtual void FillModel()
        {
            Model.ConvertedText = WikiManager.ConvertToHtml(Model.Item.Text);
            Model.Attachments = Facade.GetAttachments(Model.Item);
        }

        protected virtual void AddRefreshButton()
        {
            Model.MasterModel.ButtonsModel.Buttons.Add(new ButtonItem("LoadConverted")
            {
                Text = "Preview (Ctrl + Enter)",
                Title = "Preview currently edited wiki text. (NO SAVE is executed) Ctrl + Enter",
            });
        }
        #endregion OnBefore

        #region Actions
        public virtual ActionResult ConvertText()
        {
            BindModel(Model);
            Model.ConvertedText = Model.SourceText.IsNotEmpty()
                                    ? WikiManager.ConvertToHtml(Model.SourceText)
                                    : "not source text was found";
            return View(Str.WebControls.Converted, Model);
        }
        #endregion Actions

        #region Attachments
        public virtual ActionResult Upload(int? id)
        {
            if (!RefreshItem(id)) // no article id, no need to continue
            {
                return RedirectToAction(Str.Actions.Default);
            }

            OnBeforeDetail(id.Value);
            this.RemoveButton(Str.Business.Services.Upload); // no need to navigate to itself

            this.RemoveButton(Str.Actions.NoView.Delete)
                .RemoveButton(Str.Actions.NoView.CancelDetail);
            this.AddAction(Str.Actions.Detail, Url);
            this.InsertButton(0, Str.Actions.Detail, Url);

            FillModel();

            // submit button for Form with id="Str.WebControls.MainFormId"
            Model.MasterModel.ButtonSubmit = new ButtonItem("UploadFiles")
            {
                FormAction = "UploadFiles",
                FormController = ControllerName,
                FormRouteValues = new RouteValueDictionary(new { id }),
            };
            return View(Str.Business.Services.Upload, Model);
        }

        public virtual ActionResult UploadFiles(int? id)
        {
            if (!RefreshItem(id)) // no article id, no need to continue
            {
                return RedirectToAction(Str.Actions.Default);
            }

            var attachments = new List<Attachment>();
            foreach (string fileName in Request.Files)
            {
                var file = Request.Files[fileName];

                if (file.FileName.Equals(string.Empty))
                {
                    continue;
                }

                attachments.Add(AttachmentFacade.CreateNew(
                    file.FileName,
                    file.ContentType, file.InputStream, Model.Item));
            }

            Facade.UploadFiles(Model.Item, attachments);

            return RedirectToAction(Str.Business.Services.Upload, new { id });
        }

        public virtual ActionResult DeleteFile(int? id, string fileName, string nextAction)
        {
            if (!RefreshItem(id)) // no article id, no need to continue
            {
                return RedirectToAction(Str.Actions.Default);
            }

            Facade.DeleteFile(Model.Item, fileName);

            return RedirectToAction(nextAction ?? Str.Actions.Detail, new { id });
        }
        #endregion Attachments

        #region protected Article
        /// <summary>
        ///     Will set the Model.Item to existing Article with provided ID
        ///     or return false
        /// </summary>
        /// <param name = "id"></param>
        /// <returns></returns>
        protected virtual bool RefreshItem(int? id)
        {
            // no article id, no need to continue
            if (id.IsNull())
            {
                return false;
            }

            // currently edited Article
            if (Model.Item.IsNull()
                || !Model.Item.ID.Equals(id.Value))
            {
                var item = Facade.GetById(id.Value);
                if (item.IsNull())
                {
                    return false;
                }
                Model.Item = item;
            }
            return true;
        }
        #endregion protected Article

        #region abstract ClearFilter
        /// <summary>
        ///     Pre-sets filtering filters
        /// </summary>
        protected override ArticleFilter ClearFilter()
        {
            var filter = base.ClearFilter();
            filter.OrderBy["ReleaseDate"] = false;
            return filter;
        }
        #endregion ClearFilter

        #region properties
        public virtual IArticleCategoryFacade ArticleCategoryFacade { protected get; set; }

        public virtual IAttachmentFacade AttachmentFacade { protected get; set; }

        public override string ControllerName
        {
            get { return Str.Controllers.Article; }
        }
        #endregion properties
    }
}